package br.cefetpe.tsi.game.base.views;

import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

public class Triangle implements Shape, PathIterator {
	private Point2D.Double p1 = null, p2 = null, p3 = null;
	private double side = 0.0;
	
	public Triangle(Point2D.Double top, double side) {
		setP1(top);
		setSide(side);
		
		double p2x = (getP1().x - getSide()/2);
		double p2y = (getP1().y + (getSide()*Math.sin(Math.PI/3)));
		setP2(new Point2D.Double(p2x, p2y));
		
		double p3x = (getP1().x + getSide()/2);
		double p3y = p2y;
		setP3(new Point2D.Double(p3x, p3y));
	}
	
	public Point2D.Double getTop()
	{
		return this.p1;
	}
	
	
	public Triangle(Point2D.Double top, Point2D.Double p2, Point2D.Double p3) {
		setP1(top);
		setP2(p2);
		setP3(p3);
	}
	
	

	public double getHeight() {
		double h = (this.side * Math.sqrt(3)) / 2;
		return h;
	}
	
	public boolean contains(Point2D p) {
		boolean part1 = (p.getY() < (getP3().y - getP1().y)/(getP3().x - getP1().x) *p.getX() + (getP3().y-(getP3().y - getP1().y)/(getP3().x - getP1().x))*getP3().x);
		boolean part2 = (p.getY() < (getP2().y - getP1().y)/(getP2().x - getP1().x) *p.getX() + (getP2().y-(getP2().y - getP1().y)/(getP2().x - getP1().x))*getP2().x);
		boolean part3 = (p.getY() < getP3().y);
		if (part1 && part2 && part3){
			return true;
		} else {
			return false;
		}
	}

	public boolean contains(Rectangle2D ret) {
		//The Rectangle2D class describes a rectangle defined by 
		// a location (x, y) and dimension (w x h). 
		Point2D p2dTopLeft = new Point2D.Double(ret.getX(), ret.getY());
		Point2D p2dTopRight = new Point2D.Double(ret.getX() + ret.getWidth(), ret.getY());
		Point2D p2dBottomLeft = new Point2D.Double(ret.getX(), ret.getY() + ret.getHeight());
		Point2D p2dBottomRight = new Point2D.Double(ret.getX() + ret.getWidth(), ret.getY() + ret.getHeight());
		boolean isp2dTopLeft = contains(p2dTopLeft);
		boolean isp2dTopRight = contains(p2dTopRight);
		boolean isp2dBottomLeft = contains(p2dBottomLeft);
		boolean isp2dBottomRight = contains(p2dBottomRight);
		
		if (isp2dBottomRight && isp2dBottomLeft && isp2dTopRight && isp2dTopLeft){
			return true;
		} else {
			return false;
		}
	}

	public boolean contains(double x, double y) {
		boolean part1 = (y < (getP3().y - getP1().y)/(getP3().x - getP1().x) * x + (getP3().y-(getP3().y - getP1().y)/(getP3().x - getP1().x))*getP3().x);
		boolean part2 = (y < (getP2().y - getP1().y)/(getP2().x - getP1().x) * x + (getP2().y-(getP2().y - getP1().y)/(getP2().x - getP1().x))*getP2().x);
		boolean part3 = (y < getP3().y);
		if (part1 && part2 && part3){
			return true;
		} else {
			return false;
		}
	}

	public boolean contains(double arg0, double arg1, double arg2, double arg3) {
		Point2D p2dTopLeft = new Point2D.Double(arg0, arg1);
		Point2D p2dTopRight = new Point2D.Double(arg0 + arg2, arg1);
		Point2D p2dBottomLeft = new Point2D.Double(arg0, arg1 + arg2);
		Point2D p2dBottomRight = new Point2D.Double(arg0 + arg2, arg1 + arg2);
		boolean isp2dTopLeft = contains(p2dTopLeft);
		boolean isp2dTopRight = contains(p2dTopRight);
		boolean isp2dBottomLeft = contains(p2dBottomLeft);
		boolean isp2dBottomRight = contains(p2dBottomRight);
		
		if (isp2dBottomRight && isp2dBottomLeft && isp2dTopRight && isp2dTopLeft){
			return true;
		} else {
			return false;
		}
	}

	public Rectangle getBounds() {
		Rectangle resultBounds = new Rectangle();
		resultBounds.x = (int) (getP1().x - getSide()/2);
		resultBounds.y = (int) (getP1().y);
		resultBounds.width = (int) (getP3().x - getP2().x);
		resultBounds.height = (int) (getP2().y - getP1().y);
		return resultBounds;
	}

	public Rectangle2D getBounds2D() {
		Rectangle2D.Double resultBounds = new Rectangle2D.Double();
		resultBounds.x = (getP1().x - getSide()/2);
		resultBounds.y = (getP1().y);
		resultBounds.width = (getP3().x - getP2().x);
		resultBounds.height = (getP2().y - getP1().y);
		return resultBounds;
	}

	public PathIterator getPathIterator(AffineTransform at) {
		GeneralPath gn = new GeneralPath();
		gn.moveTo((float)getP1().x, (float)getP1().y);
		gn.lineTo((float)getP2().x, (float)getP2().y);
		gn.lineTo((float)getP3().x, (float)getP3().y);
		gn.closePath();
		return gn.getPathIterator(at);
	}

	public PathIterator getPathIterator(AffineTransform at, double flatness) {
		GeneralPath gn = new GeneralPath();
		gn.moveTo((float)getP1().x, (float)getP1().y);
		gn.lineTo((float)getP2().x, (float)getP2().y);
		gn.lineTo((float)getP3().x, (float)getP3().y);
		gn.closePath();
		return gn.getPathIterator(at);
	}

	public boolean intersects(Rectangle2D ret) {
		Point2D p2dTopLeft = new Point2D.Double(ret.getX(), ret.getY());
		Point2D p2dTopRight = new Point2D.Double(ret.getX() + ret.getWidth(), ret.getY());
		Point2D p2dBottomLeft = new Point2D.Double(ret.getX(), ret.getY() + ret.getHeight());
		Point2D p2dBottomRight = new Point2D.Double(ret.getX() + ret.getWidth(), ret.getY() + ret.getHeight());
		boolean isp2dTopLeft = contains(p2dTopLeft);
		boolean isp2dTopRight = contains(p2dTopRight);
		boolean isp2dBottomLeft = contains(p2dBottomLeft);
		boolean isp2dBottomRight = contains(p2dBottomRight);
		
		if (isp2dBottomRight || isp2dBottomLeft || isp2dTopRight || isp2dTopLeft){
			return true;
		} else {
			return false;
		}
	}

	public boolean intersects(double arg0, double arg1, double arg2, double arg3) {
		Point2D p2dTopLeft = new Point2D.Double(arg0, arg1);
		Point2D p2dTopRight = new Point2D.Double(arg0 + arg2, arg1);
		Point2D p2dBottomLeft = new Point2D.Double(arg0, arg1 + arg2);
		Point2D p2dBottomRight = new Point2D.Double(arg0 + arg2, arg1 + arg2);
		boolean isp2dTopLeft = contains(p2dTopLeft);
		boolean isp2dTopRight = contains(p2dTopRight);
		boolean isp2dBottomLeft = contains(p2dBottomLeft);
		boolean isp2dBottomRight = contains(p2dBottomRight);
		
		if (isp2dBottomRight || isp2dBottomLeft || isp2dTopRight || isp2dTopLeft){
			return true;
		} else {
			return false;
		}
	}
	
	public int currentSegment(float[] coords) {
		return getPathIterator(new AffineTransform()).currentSegment(coords);
	}

	public int currentSegment(double[] coords) {
		return getPathIterator(new AffineTransform()).currentSegment(coords);
	}

	public int getWindingRule() {
		return getPathIterator(new AffineTransform()).getWindingRule();
	}

	public boolean isDone() {
		return getPathIterator(new AffineTransform()).isDone();
	}

	public void next() {
		getPathIterator(new AffineTransform()).next();
	}
	
	private Point2D.Double getP1() {
		return p1;
	}

	private void setP1(Point2D.Double p1) {
		this.p1 = p1;
	}

	private Point2D.Double getP2() {
		return p2;
	}

	private void setP2(Point2D.Double p2) {
		this.p2 = p2;
	}

	private Point2D.Double getP3() {
		return p3;
	}

	private void setP3(Point2D.Double p3) {
		this.p3 = p3;
	}

	public double getSide() {
		return side;
	}

	private void setSide(double side) {
		this.side = side;
	}

	
}
